#include <iostream>
#include "globals.h"
#include "Perso.h"
#include "Map.h"

Perso::Perso(const char* file,int s_x,int s_y,int b_x,int b_y) {
	ox=0.0;
	oy=0.0;
	sx=s_x;
	sy=s_y;
	XIndex=0;
	YIndex=0;
	direction=0;
	deplacement=-1;
	deplacementCpt=0;
	if (!image.LoadFromFile(file)) {
		cerr << "ERROR: Did not found the File " << file << " !" << endl;
	}
	sprite.SetImage(image);
	rect.Left=0;
	rect.Top=0;
	rect.Right=image.GetWidth()/sx;
	rect.Bottom=image.GetHeight()/sy;
	sprite.SetSubRect(rect);
	//sprite.SetPosition(p_x+ox,p_y+oy);
	if(b_x>0) bx=b_x;
	else bx=0;
	if(b_y>0) by=b_y;
	else by=0;
	map=NULL;
}

Perso::~Perso() {

}

const sf::Vector2f & Perso::GetPosition () const {
	return sprite.GetPosition();
}

void Perso::Teleport (int x, int y) {
	if(map!=NULL) {
		return sprite.SetPosition( (float)x*(float)move_choice+ox+map->get_shift().x, (float)y*(float)move_choice+oy+map->get_shift().y );
	}
	else {
		return sprite.SetPosition( (float)x*(float)move_choice+ox, (float)y*(float)move_choice+oy );
	}
}

void Perso::set_map(Map &m) {
	map=&m;
	sprite.SetPosition(sprite.GetPosition().x+ox+map->get_shift().x,sprite.GetPosition().y+oy+map->get_shift().y);
}

void Perso::set_shift(float o_x,float o_y) {
	ox=o_x;
	oy=o_y;
}

sf::Vector2f Perso::get_shift() const {
	return sf::Vector2f(ox,oy);
}

int Perso::GetPosX() const {
	return (int)floor((sprite.GetPosition().x-ox-map->get_shift().x)/(float)move_choice);
}

int Perso::GetPosY() const {
	return (int)floor((sprite.GetPosition().y-oy-map->get_shift().y)/(float)move_choice);
}

int Perso::GetSizeX() const {
	return (int)floor((float)GetSprSizeX()/(float)move_choice);
}
int Perso::GetSizeY() const {
	return (int)floor((float)GetSprSizeY()/(float)move_choice);
}

int Perso::GetSprSizeX() const {
	return (int)sprite.GetSize().x;
}

int Perso::GetSprSizeY() const {
	return (int)sprite.GetSize().y;
}

void Perso::draw() const {
	App.Draw(sprite);
}

bool Perso::SetDir(int dir) {
	if(deplacement!=-1) {
		return false;
	}
	if(direction!=dir) {
		deplacementCpt=0;
		direction=dir;
		YIndex=direction;
		return false;
	}
	return true;
}

bool Perso::Begin_Move(int dir) {
	if(deplacement!=-1) {
		return false;
	}
	if(direction!=dir) {
		deplacementCpt=0;
		direction=dir;
		YIndex=direction;
		return false;
	}
	/*printf("XIndex = %d\n",XIndex);
	printf("YIndex = %d\n",YIndex);
	printf("sx = %d\n",sx);
	printf("sy = %d\n",sy);*/
	switch(dir) {
		case 0: // bas
			/*cout << (GetSprSizeX()%move_choice==0) << endl;
			cout << (GetPosY()>=map->GetMapSizeY()-GetSizeY()) << endl;
			cout << GetPosY() << endl;
			cout << map->GetMapSizeY() << endl;
			cout << GetSizeY() << endl;*/
			if(GetPosY()<map->GetMapSizeY()-1) { // aucun dépassement en bas
				if( GetSprSizeX()%move_choice==0 && GetPosY()>=map->GetMapSizeY()-(by>0?by:GetSizeY()) ) break; // si la largeur du sprite est un multiple du déplacement ET qu'il reste la largeur du sprite en bas, on ne déplace pas
				deplacement=0;
				deplacementCpt=sx;
			}
			break;
		case 1: // gauche
			if(GetPosX()>0) { // aucun dépassement à gauche
				deplacement=1;
				deplacementCpt=sx;
			}
			break;
		case 2: // droite
			/*cout << (GetSprSizeX()%move_choice==0) << endl;
			cout << (GetPosX()>=map->GetMapSizeX()-GetSizeX()) << endl;
			cout << GetPosX() << endl;
			cout << map->GetMapSizeX() << endl;
			cout << GetSizeX() << endl;*/
			if(GetPosX()<map->GetMapSizeX()-1) { // aucun dépassement à droite
				if( GetSprSizeX()%move_choice==0 && GetPosX()>=map->GetMapSizeX()-(bx>0?bx:GetSizeX()) ) break; // si la largeur du sprite est un multiple du déplacement ET qu'il reste la largeur du sprite à droite, on ne déplace pas
				deplacement=2;
				deplacementCpt=sx;
			}
			break;
		case 3: // haut
			if(GetPosY()>0) { // aucun dépassement en haut
				deplacement=3;
				deplacementCpt=sx;
			}
			break;
		default: /* -1 */
			return false;
			break;
	}
	if(deplacementCpt==0) deplacement=-1; // remplace le test de débordement de l'écran dans calc_position
	return true;
}

bool Perso::Move() {
	bool result=false;
	if(deplacement!=-1) {
		/* calcul de la position */
		if(deplacementCpt<=0) deplacement=-1;
		//cout << "move begin deplacment" << endl;
		switch(deplacement) {
			case 0: // bas
				--deplacementCpt;
				XIndex=(XIndex+1)%sx;
				sprite.SetY( sprite.GetPosition().y + (float)(move_choice/sx) );
				result=true;
				break;
			case 1: // gauche
				--deplacementCpt;
				XIndex=(XIndex+1)%sx;
				sprite.SetX( sprite.GetPosition().x - (float)(move_choice/sx) );
				result=true;
				break;
			case 2: // droite
				--deplacementCpt;
				XIndex=(XIndex+1)%sx;
				sprite.SetX( sprite.GetPosition().x + (float)(move_choice/sx) );
				result=true;
				break;
			case 3: // haut
				--deplacementCpt;
				XIndex=(XIndex+1)%sx;
				sprite.SetY( sprite.GetPosition().y - (float)(move_choice/sx) );
				result=true;
				break;
			case -2:
			case -1:
				XIndex=0;
				deplacementCpt=0;
				deplacement=-1;
				result=false;
				break;
			default:
				break;
		}
		if(deplacementCpt<=0) {
			XIndex=0;
			deplacementCpt=0;
			deplacement=-1;
			result=false;
		}
	}
	/* On va chercher la coordonnee du sprite à afficher dans l'image */
	rect.Left=(XIndex%sx)*(image.GetWidth()/sx);
	rect.Right=(XIndex%sx+1)*(image.GetWidth()/sx);
	rect.Top=(YIndex%sy)*(image.GetHeight()/sy);
	rect.Bottom=(YIndex%sy+1)*(image.GetHeight()/sy);
	sprite.SetSubRect(rect);
	return result;
}
